This study is a replication of Sun & Breheny (2019) with the web-based eye-tracking paradigm using the javascript webgazer library.

Here’s the experiment we’re analyzing.

library(tidyverse)
library(lme4)
library(ggplot2)
library("readxl")

# load helper scripts
source("helpers.R")

# load target word onsets
audio_info = read_excel("../data/audiotimes.xlsx")

# set color-blind-friendly color palette
cbPalette <- c("#56B4E9", "#D55E00", "#009E73","#999999", "#E69F00","#009E73","#56B4E9", "#D55E00", "#009E73","#999999", "#E69F00","#009E73","#56B4E9", "#D55E00", "#009E73","#999999", "#E69F00","#009E73","#56B4E9", "#D55E00", "#009E73","#999999", "#E69F00","#009E73")

# load data 
d = read.csv('../data/sunbreheny_webgazer_pilot2-merged.csv') %>%
  select(-location1,-location2,-location3,-location4,-location5,-location6,-location7,-location8,-location9,-location10,-target_figure,-target_object,-target_num_object,-error) %>% 
  filter(trial_type=="Exp") %>%
  mutate(target_location = ifelse((target1==7 | target2==7),"topleft",ifelse((target1==8 | target2==8),"bottomleft",ifelse((target1==9 | target2==9),"topright",ifelse((target1==10 | target2==10),"bottomright",NA))))) %>%
  mutate(competitor_location = ifelse((competitor1==7 | competitor2==7),"topleft",ifelse((competitor1==8 | competitor2==8),"bottomleft",ifelse((competitor1==9 | competitor2==9),"topright",ifelse((competitor1==10 | competitor2==10),"bottomright", NA))))) %>%
  left_join(audio_info,by=c("audio" = "Prime")) %>% #for testing: TODO
  filter(as.character(proliferate.condition)!= "list1") %>%
  filter(as.character(proliferate.condition)!= "list2") %>%
  filter(as.character(proliferate.condition)!= "list3")

# formatting
d$webgazer_time = gsub("\\[","",d$webgazer_time)
d$webgazer_time= gsub("\\]","",d$webgazer_time)
d$x = gsub("\\[","",d$x)
d$x = gsub("\\]","",d$x)
d$y = gsub("\\[","",d$y)
d$y = gsub("\\]","",d$y)

Exclude trials with wrong selections and plot subject information.

d = d %>% 
  mutate(selection_correct = ifelse(as.character(response) == as.character(target1),1, ifelse(as.character(response) == as.character(target2),1,0)),language = tolower(subject_information.language))

table(d$selection_correct)

  0   1 
  1 107 
d = d %>% 
  filter(selection_correct==1)

participants = d %>% 
  select(workerid,subject_information.accuracy,subject_information.age,subject_information.camblock,subject_information.comments, subject_information.eyesight, subject_information.eyesight_task, subject_information.gender, subject_information.headphones, language, subject_information.previous_accuracy_attempts, subject_information.time_in_minutes) %>% 
  unique()

# number of unique participants:
nrow(participants) 
[1] 3
# distribution of participant gender
table(participants$subject_information.gender)

 Male Woman 
    2     1 
# distribution of completion times
summary(participants$subject_information.time_in_minutes)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  12.11   12.82   13.52   13.32   13.92   14.31 
ggplot(participants, aes(x=subject_information.time_in_minutes)) +
  geom_histogram()


# distribution of calibration accuracy
summary(participants$subject_information.accuracy)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  55.00   63.50   72.00   66.67   72.50   73.00 
ggplot(participants, aes(x=subject_information.accuracy)) +
  geom_histogram()


# distribution of ages
summary(participants$subject_information.age)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  24.00   25.00   26.00   40.33   48.50   71.00 
ggplot(participants, aes(x=subject_information.age)) +
  geom_histogram()


# eyesight information
ggplot(participants, aes(x=subject_information.eyesight,fill=subject_information.eyesight_task)) +
  geom_histogram(stat="count")


# distribution of camera views -- some people continued to see camera view even during experiment (bug we haven't figured out yet how to fix)
ggplot(participants, aes(x=subject_information.camblock,fill=subject_information.camblock)) +
  geom_histogram(stat="count")


# distribution of headphone use
ggplot(participants, aes(x=subject_information.headphones)) +
  geom_histogram(stat="count")


# distribution of native languages
ggplot(participants, aes(x=language)) +
  geom_histogram(stat="count") +
  theme(axis.text.x=element_text(angle=45, hjust=1,vjust=1))

Separate time and x/y coordinates into separate data points, one per row, and define regions of interest (ROIs).

Bin samples and align time to the onset of words.

# relevant time columns------------
# trial_start: unix time at the beginning of the trial (when images are displayed)
# audio_play_unix: unix time at the beginning of the audio (after 1sec display preview)
# webgazer_time: elapsed time since webgazer started
# unix_tlist: unix time of each webgazer_time sample
# unix_rt: unix time of selection
# response_time: response time in ms (trial_start - unix_rt)

first_samples = dd %>% 
  group_by(workerid,slide_number) %>% 
  summarize(first_sample = min(webgazer_time))

# total number of samples:
nrow(first_samples)

# set size of time bins to collapse over
binsize = 60

# TODO: FIX EVERYTHING AFTER THIS --- 
# bin samples and align to target word onset
dd_binned = dd %>% 
  left_join(first_samples,by=c("workerid","slide_number")) %>% 
  mutate(relative_time = webgazer_time-first_sample) %>% 
  mutate(relative_time_bin=floor(relative_time/binsize)) %>% 
  mutate(binned_time_relative = relative_time_bin*binsize)

Plot proportions of looks to all regions (target, competitor, center, other)

# aggregate looks (compute proportions of looks to each region in each time bin and condition; add 95% bootstrapped confidence intervals)
agr = dd_binned %>% 
  group_by(condition,binned_time_relative) %>% 
  summarize(target_prop=mean(target_look),target_CILow=ci.low(target_look),target_CIHigh=ci.high(target_look),competitor_prop=mean(competitor_look),competitor_CILow=ci.low(competitor_look),competitor_CIHigh=ci.high(competitor_look),center_prop=mean(center_look),center_CILow=ci.low(center_look),center_CIHigh=ci.high(center_look),other_prop=mean(other_look),other_CILow=ci.low(other_look),other_CIHigh=ci.high(other_look)) %>% 
  ungroup() %>% 
  mutate(target_ymin=target_prop-target_CILow,target_ymax=target_prop+target_CIHigh,competitor_ymin=competitor_prop-competitor_CILow,competitor_ymax=competitor_prop+competitor_CIHigh,center_ymin=center_prop-center_CILow,center_ymax=center_prop+center_CIHigh,other_ymin=other_prop-other_CILow,other_ymax=other_prop+other_CIHigh)

# prepare data for plotting
long_props = agr %>% 
  select(condition,binned_time_relative,target_prop,competitor_prop,center_prop,other_prop) %>% 
  pivot_longer(cols = target_prop:other_prop,names_to=c("region"),values_to=c("proportion")) %>% 
  separate(region,c("region",NA))

long_ymin = agr %>% 
  select(condition,binned_time_relative,target_ymin,competitor_ymin,center_ymin,other_ymin) %>% 
  pivot_longer(cols = target_ymin:other_ymin,names_to=c("region"),values_to=c("ymin")) %>% 
  separate(region,c("region",NA))

long_ymax = agr %>% 
  select(condition,binned_time_relative,target_ymax,competitor_ymax,center_ymax,other_ymax) %>% 
  pivot_longer(cols = target_ymax:other_ymax,names_to=c("region"),values_to=c("ymax")) %>% 
  separate(region,c("region",NA))

toplot = long_props %>% 
  left_join(long_ymin,by=c("condition","binned_time_relative","region")) %>% 
  left_join(long_ymax,by=c("condition","binned_time_relative","region")) %>% 
  mutate(region = fct_relevel(region,"target","competitor","center"))

LS0tCnRpdGxlOiAiU3VuICYgQnJlaGVueSAoMjAxOSkgd2ViZ2F6ZXIgcmVwbGljYXRpb24iCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAotLS0KClRoaXMgc3R1ZHkgaXMgYSByZXBsaWNhdGlvbiBvZiBTdW4gJiBCcmVoZW55ICgyMDE5KSB3aXRoIHRoZSB3ZWItYmFzZWQgZXllLXRyYWNraW5nIHBhcmFkaWdtIHVzaW5nIHRoZSBqYXZhc2NyaXB0IHdlYmdhemVyIGxpYnJhcnkuCgpbSGVyZV0oaHR0cHM6Ly9tYWRpZ2FuYnJvZHNreS5naXRodWIuaW8vZXlldHJhY2tpbmdfcmVwbGljYXRpb24vZXhwZXJpbWVudHMvU3VuQnJlaGVueV93ZWJnYXplci9waWxvdC9saXN0MSkncyB0aGUgZXhwZXJpbWVudCB3ZSdyZSBhbmFseXppbmcuCgpgYGB7ciwgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGxtZTQpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSgicmVhZHhsIikKCiMgbG9hZCBoZWxwZXIgc2NyaXB0cwpzb3VyY2UoImhlbHBlcnMuUiIpCgojIGxvYWQgdGFyZ2V0IHdvcmQgb25zZXRzCmF1ZGlvX2luZm8gPSByZWFkX2V4Y2VsKCIuLi9kYXRhL2F1ZGlvdGltZXMueGxzeCIpCgojIHNldCBjb2xvci1ibGluZC1mcmllbmRseSBjb2xvciBwYWxldHRlCmNiUGFsZXR0ZSA8LSBjKCIjNTZCNEU5IiwgIiNENTVFMDAiLCAiIzAwOUU3MyIsIiM5OTk5OTkiLCAiI0U2OUYwMCIsIiMwMDlFNzMiLCIjNTZCNEU5IiwgIiNENTVFMDAiLCAiIzAwOUU3MyIsIiM5OTk5OTkiLCAiI0U2OUYwMCIsIiMwMDlFNzMiLCIjNTZCNEU5IiwgIiNENTVFMDAiLCAiIzAwOUU3MyIsIiM5OTk5OTkiLCAiI0U2OUYwMCIsIiMwMDlFNzMiLCIjNTZCNEU5IiwgIiNENTVFMDAiLCAiIzAwOUU3MyIsIiM5OTk5OTkiLCAiI0U2OUYwMCIsIiMwMDlFNzMiKQoKIyBsb2FkIGRhdGEgCmQgPSByZWFkLmNzdignLi4vZGF0YS9zdW5icmVoZW55X3dlYmdhemVyX3BpbG90Mi1tZXJnZWQuY3N2JykgJT4lCiAgc2VsZWN0KC1sb2NhdGlvbjEsLWxvY2F0aW9uMiwtbG9jYXRpb24zLC1sb2NhdGlvbjQsLWxvY2F0aW9uNSwtbG9jYXRpb242LC1sb2NhdGlvbjcsLWxvY2F0aW9uOCwtbG9jYXRpb245LC1sb2NhdGlvbjEwLC10YXJnZXRfZmlndXJlLC10YXJnZXRfb2JqZWN0LC10YXJnZXRfbnVtX29iamVjdCwtZXJyb3IpICU+JSAKICBmaWx0ZXIodHJpYWxfdHlwZT09IkV4cCIpICU+JQogIG11dGF0ZSh0YXJnZXRfbG9jYXRpb24gPSBpZmVsc2UoKHRhcmdldDE9PTcgfCB0YXJnZXQyPT03KSwidG9wbGVmdCIsaWZlbHNlKCh0YXJnZXQxPT04IHwgdGFyZ2V0Mj09OCksImJvdHRvbWxlZnQiLGlmZWxzZSgodGFyZ2V0MT09OSB8IHRhcmdldDI9PTkpLCJ0b3ByaWdodCIsaWZlbHNlKCh0YXJnZXQxPT0xMCB8IHRhcmdldDI9PTEwKSwiYm90dG9tcmlnaHQiLE5BKSkpKSkgJT4lCiAgbXV0YXRlKGNvbXBldGl0b3JfbG9jYXRpb24gPSBpZmVsc2UoKGNvbXBldGl0b3IxPT03IHwgY29tcGV0aXRvcjI9PTcpLCJ0b3BsZWZ0IixpZmVsc2UoKGNvbXBldGl0b3IxPT04IHwgY29tcGV0aXRvcjI9PTgpLCJib3R0b21sZWZ0IixpZmVsc2UoKGNvbXBldGl0b3IxPT05IHwgY29tcGV0aXRvcjI9PTkpLCJ0b3ByaWdodCIsaWZlbHNlKChjb21wZXRpdG9yMT09MTAgfCBjb21wZXRpdG9yMj09MTApLCJib3R0b21yaWdodCIsIE5BKSkpKSkgJT4lCiAgbGVmdF9qb2luKGF1ZGlvX2luZm8sYnk9YygiYXVkaW8iID0gIlByaW1lIikpICU+JQogIGZpbHRlcihzdHJfZGV0ZWN0KHByb2xpZmVyYXRlLmNvbmRpdGlvbiwiY29uZGl0aW9uIikpICNvbmx5IGNvbmRpdGlvbiwgY29uZGl0aW9uMSBhbmQgY29uZGl0aW9uMiBhcmUgaW4gdGhlIGZpbmFsIGZvcm1hdCAocmVzdCB3ZXJlIHByZXZpb3VzIHBpbG90cyEhISkKCiMgZm9ybWF0dGluZwpkJHdlYmdhemVyX3RpbWUgPSBnc3ViKCJcXFsiLCIiLGQkd2ViZ2F6ZXJfdGltZSkKZCR3ZWJnYXplcl90aW1lPSBnc3ViKCJcXF0iLCIiLGQkd2ViZ2F6ZXJfdGltZSkKZCR4ID0gZ3N1YigiXFxbIiwiIixkJHgpCmQkeCA9IGdzdWIoIlxcXSIsIiIsZCR4KQpkJHkgPSBnc3ViKCJcXFsiLCIiLGQkeSkKZCR5ID0gZ3N1YigiXFxdIiwiIixkJHkpCmBgYAoKCkV4Y2x1ZGUgdHJpYWxzIHdpdGggd3Jvbmcgc2VsZWN0aW9ucyBhbmQgcGxvdCBzdWJqZWN0IGluZm9ybWF0aW9uLgpgYGB7cixtZXNzYWdlPUYsd2FybmluZz1GfQpkID0gZCAlPiUgCiAgbXV0YXRlKHNlbGVjdGlvbl9jb3JyZWN0ID0gaWZlbHNlKGFzLmNoYXJhY3RlcihyZXNwb25zZSkgPT0gYXMuY2hhcmFjdGVyKHRhcmdldDEpLDEsIGlmZWxzZShhcy5jaGFyYWN0ZXIocmVzcG9uc2UpID09IGFzLmNoYXJhY3Rlcih0YXJnZXQyKSwxLDApKSxsYW5ndWFnZSA9IHRvbG93ZXIoc3ViamVjdF9pbmZvcm1hdGlvbi5sYW5ndWFnZSkpCgp0YWJsZShkJHNlbGVjdGlvbl9jb3JyZWN0KQoKZCA9IGQgJT4lIAogIGZpbHRlcihzZWxlY3Rpb25fY29ycmVjdD09MSkKCnBhcnRpY2lwYW50cyA9IGQgJT4lIAogIHNlbGVjdCh3b3JrZXJpZCxzdWJqZWN0X2luZm9ybWF0aW9uLmFjY3VyYWN5LHN1YmplY3RfaW5mb3JtYXRpb24uYWdlLHN1YmplY3RfaW5mb3JtYXRpb24uY2FtYmxvY2ssc3ViamVjdF9pbmZvcm1hdGlvbi5jb21tZW50cywgc3ViamVjdF9pbmZvcm1hdGlvbi5leWVzaWdodCwgc3ViamVjdF9pbmZvcm1hdGlvbi5leWVzaWdodF90YXNrLCBzdWJqZWN0X2luZm9ybWF0aW9uLmdlbmRlciwgc3ViamVjdF9pbmZvcm1hdGlvbi5oZWFkcGhvbmVzLCBsYW5ndWFnZSwgc3ViamVjdF9pbmZvcm1hdGlvbi5wcmV2aW91c19hY2N1cmFjeV9hdHRlbXB0cywgc3ViamVjdF9pbmZvcm1hdGlvbi50aW1lX2luX21pbnV0ZXMpICU+JSAKICB1bmlxdWUoKQoKIyBudW1iZXIgb2YgdW5pcXVlIHBhcnRpY2lwYW50czoKbnJvdyhwYXJ0aWNpcGFudHMpIAoKIyBkaXN0cmlidXRpb24gb2YgcGFydGljaXBhbnQgZ2VuZGVyCnRhYmxlKHBhcnRpY2lwYW50cyRzdWJqZWN0X2luZm9ybWF0aW9uLmdlbmRlcikKCiMgZGlzdHJpYnV0aW9uIG9mIGNvbXBsZXRpb24gdGltZXMKc3VtbWFyeShwYXJ0aWNpcGFudHMkc3ViamVjdF9pbmZvcm1hdGlvbi50aW1lX2luX21pbnV0ZXMpCmdncGxvdChwYXJ0aWNpcGFudHMsIGFlcyh4PXN1YmplY3RfaW5mb3JtYXRpb24udGltZV9pbl9taW51dGVzKSkgKwogIGdlb21faGlzdG9ncmFtKCkKCiMgZGlzdHJpYnV0aW9uIG9mIGNhbGlicmF0aW9uIGFjY3VyYWN5CnN1bW1hcnkocGFydGljaXBhbnRzJHN1YmplY3RfaW5mb3JtYXRpb24uYWNjdXJhY3kpCmdncGxvdChwYXJ0aWNpcGFudHMsIGFlcyh4PXN1YmplY3RfaW5mb3JtYXRpb24uYWNjdXJhY3kpKSArCiAgZ2VvbV9oaXN0b2dyYW0oKQoKIyBkaXN0cmlidXRpb24gb2YgYWdlcwpzdW1tYXJ5KHBhcnRpY2lwYW50cyRzdWJqZWN0X2luZm9ybWF0aW9uLmFnZSkKZ2dwbG90KHBhcnRpY2lwYW50cywgYWVzKHg9c3ViamVjdF9pbmZvcm1hdGlvbi5hZ2UpKSArCiAgZ2VvbV9oaXN0b2dyYW0oKQoKIyBleWVzaWdodCBpbmZvcm1hdGlvbgpnZ3Bsb3QocGFydGljaXBhbnRzLCBhZXMoeD1zdWJqZWN0X2luZm9ybWF0aW9uLmV5ZXNpZ2h0LGZpbGw9c3ViamVjdF9pbmZvcm1hdGlvbi5leWVzaWdodF90YXNrKSkgKwogIGdlb21faGlzdG9ncmFtKHN0YXQ9ImNvdW50IikKCiMgZGlzdHJpYnV0aW9uIG9mIGNhbWVyYSB2aWV3cyAtLSBzb21lIHBlb3BsZSBjb250aW51ZWQgdG8gc2VlIGNhbWVyYSB2aWV3IGV2ZW4gZHVyaW5nIGV4cGVyaW1lbnQgKGJ1ZyB3ZSBoYXZlbid0IGZpZ3VyZWQgb3V0IHlldCBob3cgdG8gZml4KQpnZ3Bsb3QocGFydGljaXBhbnRzLCBhZXMoeD1zdWJqZWN0X2luZm9ybWF0aW9uLmNhbWJsb2NrLGZpbGw9c3ViamVjdF9pbmZvcm1hdGlvbi5jYW1ibG9jaykpICsKICBnZW9tX2hpc3RvZ3JhbShzdGF0PSJjb3VudCIpCgojIGRpc3RyaWJ1dGlvbiBvZiBoZWFkcGhvbmUgdXNlCmdncGxvdChwYXJ0aWNpcGFudHMsIGFlcyh4PXN1YmplY3RfaW5mb3JtYXRpb24uaGVhZHBob25lcykpICsKICBnZW9tX2hpc3RvZ3JhbShzdGF0PSJjb3VudCIpCgojIGRpc3RyaWJ1dGlvbiBvZiBuYXRpdmUgbGFuZ3VhZ2VzCmdncGxvdChwYXJ0aWNpcGFudHMsIGFlcyh4PWxhbmd1YWdlKSkgKwogIGdlb21faGlzdG9ncmFtKHN0YXQ9ImNvdW50IikgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSx2anVzdD0xKSkKYGBgCgpTZXBhcmF0ZSB0aW1lIGFuZCB4L3kgY29vcmRpbmF0ZXMgaW50byBzZXBhcmF0ZSBkYXRhIHBvaW50cywgb25lIHBlciByb3csIGFuZCBkZWZpbmUgcmVnaW9ucyBvZiBpbnRlcmVzdCAoUk9JcykuCmBgYHtyLG1lc3NhZ2U9Rix3YXJuaW5nPUZ9CiMgc2V0IHdpZHRoIGFuZCBoZWlnaHQgb2YgUk9JcwppbWd3aWR0aCA9IDEwNyArIDExMCAjIGJveS9naXJsICsgb2JqZWN0cwppbWdoZWlnaHQgPSAyMDAgIyBib3kvZ2lybCAodGFsbGVyIHRoYW4gb2JqZWN0cykKCmNlbnRlcl9pbWd3aWR0aCA9IDIyMCAjIG9iamVjdHMKY2VudGVyX2ltZ2hlaWdodCA9IDExMCAjIG9iamVjdHMKCnNjZW5lX3dpZHRoID0gMTI4MCAjIGV2ZXJ5dGhpbmcgdGFrZXMgcGxhY2UgaW4gYSBjZW50cmFsICdzY2VuZScgb2YgIDEyODAgeCA3NTAgcGl4ZWxzIApzY2VuZV9oZWlnaHQgPSA3NTAgCgpkZCA9IGQgJT4lCiAgc2VwYXJhdGVfcm93cyh3ZWJnYXplcl90aW1lLHgseSxjb252ZXJ0PVRSVUUsIHNlcD0iLCIpICU+JSAKICBtdXRhdGUoeF9jZW50ZXIgPSAoc3lzdGVtLndpbmRvd1cvMiksIHlfY2VudGVyID0gKHN5c3RlbS53aW5kb3dILzIpLAogICAgICAgICAgIEFPSV90b3BsZWZ0X3hfbWluID0geF9jZW50ZXIgLSAoc2NlbmVfd2lkdGgvMiksCiAgICAgICAgICAgQU9JX3RvcGxlZnRfeF9tYXggPSB4X2NlbnRlciAtIChzY2VuZV93aWR0aC8yKSArIGltZ3dpZHRoLAogICAgICAgICAgIEFPSV90b3BsZWZ0X3lfbWluID0geV9jZW50ZXIgKyAoc2NlbmVfaGVpZ2h0LzIpIC0gaW1naGVpZ2h0LAogICAgICAgICAgIEFPSV90b3BsZWZ0X3lfbWF4ID0geV9jZW50ZXIgKyAoc2NlbmVfaGVpZ2h0LzIpLAogICAgICAgICAKICAgICAgICAgICBBT0lfYm90dG9tbGVmdF94X21pbiA9IHhfY2VudGVyIC0gKHNjZW5lX3dpZHRoLzIpLAogICAgICAgICAgIEFPSV9ib3R0b21sZWZ0X3hfbWF4ID0geF9jZW50ZXIgLSAoc2NlbmVfd2lkdGgvMikgKyBpbWd3aWR0aCwKICAgICAgICAgICBBT0lfYm90dG9tbGVmdF95X21pbiA9IHlfY2VudGVyIC0gKHNjZW5lX2hlaWdodC8yKSwKICAgICAgICAgICBBT0lfYm90dG9tbGVmdF95X21heCA9IHlfY2VudGVyIC0gKHNjZW5lX2hlaWdodC8yKSArIGltZ2hlaWdodCwKICAgICAgICAgCiAgICAgICAgICAgQU9JX3RvcHJpZ2h0X3hfbWluID0geF9jZW50ZXIgKyAoc2NlbmVfd2lkdGgvMikgLSBpbWd3aWR0aCwKICAgICAgICAgICBBT0lfdG9wcmlnaHRfeF9tYXggPSB4X2NlbnRlciArIChzY2VuZV93aWR0aC8yKSwKICAgICAgICAgICBBT0lfdG9wcmlnaHRfeV9taW4gPSB5X2NlbnRlciArIChzY2VuZV9oZWlnaHQvMikgLSBpbWdoZWlnaHQsCiAgICAgICAgICAgQU9JX3RvcHJpZ2h0X3lfbWF4ID0geV9jZW50ZXIgKyAoc2NlbmVfaGVpZ2h0LzIpLAogICAgICAgICAKICAgICAgICAgICBBT0lfYm90dG9tcmlnaHRfeF9taW4gPSB4X2NlbnRlciArIChzY2VuZV93aWR0aC8yKSAtIGltZ3dpZHRoLAogICAgICAgICAgIEFPSV9ib3R0b21yaWdodF94X21heCA9IHhfY2VudGVyICsgKHNjZW5lX3dpZHRoLzIpLAogICAgICAgICAgIEFPSV9ib3R0b21yaWdodF95X21pbiA9IHlfY2VudGVyIC0gKHNjZW5lX2hlaWdodC8yKSwKICAgICAgICAgICBBT0lfYm90dG9tcmlnaHRfeV9tYXggPSB5X2NlbnRlciAtIChzY2VuZV9oZWlnaHQvMikgKyBpbWdoZWlnaHQsCiAgICAgICAgIAogICAgICAgICAgIEFPSV9jZW50ZXJfeF9taW4gPSB4X2NlbnRlciAtIChjZW50ZXJfaW1nd2lkdGgvMiksCiAgICAgICAgICAgQU9JX2NlbnRlcl94X21heCA9IHhfY2VudGVyICsgKGNlbnRlcl9pbWd3aWR0aC8yKSwKICAgICAgICAgICBBT0lfY2VudGVyX3lfbWluID0geV9jZW50ZXIgLSAoY2VudGVyX2ltZ2hlaWdodC8yKSwKICAgICAgICAgICBBT0lfY2VudGVyX3lfbWF4ID0geV9jZW50ZXIgKyAoY2VudGVyX2ltZ2hlaWdodC8yKSkgJT4lCiAgCiAgbXV0YXRlKGxvb2sgPSBjYXNlX3doZW4oeDxBT0lfdG9wbGVmdF94X21heCAmIHg+QU9JX3RvcGxlZnRfeF9taW4gJiB5PEFPSV90b3BsZWZ0X3lfbWF4ICYgeT5BT0lfdG9wbGVmdF95X21pbiB+ICJ0b3BsZWZ0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICB4PEFPSV9ib3R0b21sZWZ0X3hfbWF4ICYgeD5BT0lfYm90dG9tbGVmdF94X21pbiAmIHk8QU9JX2JvdHRvbWxlZnRfeV9tYXggJiB5ID4gQU9JX2JvdHRvbWxlZnRfeV9taW4gfiAiYm90dG9tbGVmdCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgeDxBT0lfdG9wcmlnaHRfeF9tYXggJiB4PkFPSV90b3ByaWdodF94X21pbiAmIHk8QU9JX3RvcHJpZ2h0X3lfbWF4ICYgeT5BT0lfdG9wcmlnaHRfeV9taW4gfiAidG9wcmlnaHQiLAogICAgICAgICAgICAgICAgICAgICAgICAgIHg8QU9JX2JvdHRvbXJpZ2h0X3hfbWF4ICYgeD5BT0lfYm90dG9tcmlnaHRfeF9taW4gJiB5PEFPSV9ib3R0b21yaWdodF95X21heCAmIHk+QU9JX2JvdHRvbXJpZ2h0X3lfbWluIH4gImJvdHRvbXJpZ2h0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICB4PEFPSV9jZW50ZXJfeF9tYXggJiB4PkFPSV9jZW50ZXJfeF9taW4gJiB5PEFPSV9jZW50ZXJfeV9tYXggJiB5PkFPSV9jZW50ZXJfeV9taW4gfiAiY2VudGVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAib3RoZXIiKSkgJT4lCiAgbXV0YXRlKFJPSSA9IGNhc2Vfd2hlbihsb29rPT10YXJnZXRfbG9jYXRpb24gfiAidGFyZ2V0IiwKICAgICAgICAgICAgICAgICAgICAgICAgIGxvb2s9PWNvbXBldGl0b3JfbG9jYXRpb24gfiAiY29tcGV0aXRvciIsCiAgICAgICAgICAgICAgICAgICAgICAgICBsb29rPT0iY2VudGVyIiB+ICJjZW50ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJvdGhlciIpKSAlPiUKICBtdXRhdGUodGFyZ2V0X2xvb2sgPSBpZmVsc2UoUk9JID09ICJ0YXJnZXQiLCAxLCAwKSwgY29tcGV0aXRvcl9sb29rID0gaWZlbHNlKFJPSSA9PSAiY29tcGV0aXRvciIsIDEsIDApLCBjZW50ZXJfbG9vayA9IGlmZWxzZShST0kgPT0gImNlbnRlciIsIDEsIDApLCBvdGhlcl9sb29rID0gaWZlbHNlKFJPSSA9PSAib3RoZXIiLCAxLCAwKSkgJT4lCiAgZmlsdGVyKGxvb2shPSJvdGhlciIpICNUT0RPOiByZW1vdmUgb3RoZXIgbG9va3Mgb3V0c2lkZSB3aW5kb3c/CgojIHNhbml0eSBjaGVjayB0aGF0IFJPSXMgYXJlIGdldHRpbmcgY29ycmVjdGx5IGFzc2lnbmVkCmdncGxvdChkZCwgYWVzKHg9eCx5PXksY29sb3I9bG9vaykpICsKICBnZW9tX3BvaW50KCkgKwogIGZhY2V0X3dyYXAofndvcmtlcmlkLHNjYWxlcz0iZnJlZSIpCmBgYAoKQmluIHNhbXBsZXMgYW5kIGFsaWduIHRpbWUgdG8gdGhlIG9uc2V0IG9mIHdvcmRzLgpgYGB7cixtZXNzYWdlPUYsd2FybmluZz1GfQojIHJlbGV2YW50IHRpbWUgY29sdW1ucy0tLS0tLS0tLS0tLQojIHRyaWFsX3N0YXJ0OiB1bml4IHRpbWUgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgdHJpYWwgKHdoZW4gaW1hZ2VzIGFyZSBkaXNwbGF5ZWQpCiMgYXVkaW9fcGxheV91bml4OiB1bml4IHRpbWUgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgYXVkaW8gKGFmdGVyIDFzZWMgZGlzcGxheSBwcmV2aWV3KQojIHdlYmdhemVyX3RpbWU6IGVsYXBzZWQgdGltZSBzaW5jZSB3ZWJnYXplciBzdGFydGVkCiMgdW5peF90bGlzdDogdW5peCB0aW1lIG9mIGVhY2ggd2ViZ2F6ZXJfdGltZSBzYW1wbGUKIyB1bml4X3J0OiB1bml4IHRpbWUgb2Ygc2VsZWN0aW9uCiMgcmVzcG9uc2VfdGltZTogcmVzcG9uc2UgdGltZSBpbiBtcyAodHJpYWxfc3RhcnQgLSB1bml4X3J0KQoKZmlyc3Rfc2FtcGxlcyA9IGRkICU+JSAKICBncm91cF9ieSh3b3JrZXJpZCxzbGlkZV9udW1iZXIpICU+JSAKICBzdW1tYXJpemUoZmlyc3Rfc2FtcGxlID0gbWluKHdlYmdhemVyX3RpbWUpKQoKIyB0b3RhbCBudW1iZXIgb2Ygc2FtcGxlczoKbnJvdyhmaXJzdF9zYW1wbGVzKQoKIyBzZXQgc2l6ZSBvZiB0aW1lIGJpbnMgdG8gY29sbGFwc2Ugb3ZlcgpiaW5zaXplID0gNjAKCiMgVE9ETzogRklYIEVWRVJZVEhJTkcgQUZURVIgVEhJUyAtLS0gCiMgYmluIHNhbXBsZXMgYW5kIGFsaWduIHRvIHRhcmdldCB3b3JkIG9uc2V0CmRkX2Jpbm5lZCA9IGRkICU+JSAKICBsZWZ0X2pvaW4oZmlyc3Rfc2FtcGxlcyxieT1jKCJ3b3JrZXJpZCIsInNsaWRlX251bWJlciIpKSAlPiUgCiAgbXV0YXRlKHJlbGF0aXZlX3RpbWUgPSB3ZWJnYXplcl90aW1lLWZpcnN0X3NhbXBsZSkgJT4lIAogIG11dGF0ZShyZWxhdGl2ZV90aW1lX2Jpbj1mbG9vcihyZWxhdGl2ZV90aW1lL2JpbnNpemUpKSAlPiUgCiAgbXV0YXRlKGJpbm5lZF90aW1lX3JlbGF0aXZlID0gcmVsYXRpdmVfdGltZV9iaW4qYmluc2l6ZSkKYGBgCgpQbG90IHByb3BvcnRpb25zIG9mIGxvb2tzIHRvIGFsbCByZWdpb25zICh0YXJnZXQsIGNvbXBldGl0b3IsIGNlbnRlciwgb3RoZXIpCmBgYHtyIG1lc3NhZ2U9Riwgd2FybmluZz1GfQojIGFnZ3JlZ2F0ZSBsb29rcyAoY29tcHV0ZSBwcm9wb3J0aW9ucyBvZiBsb29rcyB0byBlYWNoIHJlZ2lvbiBpbiBlYWNoIHRpbWUgYmluIGFuZCBjb25kaXRpb247IGFkZCA5NSUgYm9vdHN0cmFwcGVkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzKQphZ3IgPSBkZF9iaW5uZWQgJT4lIAogIGdyb3VwX2J5KGNvbmRpdGlvbixiaW5uZWRfdGltZV9yZWxhdGl2ZSkgJT4lIAogIHN1bW1hcml6ZSh0YXJnZXRfcHJvcD1tZWFuKHRhcmdldF9sb29rKSx0YXJnZXRfQ0lMb3c9Y2kubG93KHRhcmdldF9sb29rKSx0YXJnZXRfQ0lIaWdoPWNpLmhpZ2godGFyZ2V0X2xvb2spLGNvbXBldGl0b3JfcHJvcD1tZWFuKGNvbXBldGl0b3JfbG9vayksY29tcGV0aXRvcl9DSUxvdz1jaS5sb3coY29tcGV0aXRvcl9sb29rKSxjb21wZXRpdG9yX0NJSGlnaD1jaS5oaWdoKGNvbXBldGl0b3JfbG9vayksY2VudGVyX3Byb3A9bWVhbihjZW50ZXJfbG9vayksY2VudGVyX0NJTG93PWNpLmxvdyhjZW50ZXJfbG9vayksY2VudGVyX0NJSGlnaD1jaS5oaWdoKGNlbnRlcl9sb29rKSxvdGhlcl9wcm9wPW1lYW4ob3RoZXJfbG9vayksb3RoZXJfQ0lMb3c9Y2kubG93KG90aGVyX2xvb2spLG90aGVyX0NJSGlnaD1jaS5oaWdoKG90aGVyX2xvb2spKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBtdXRhdGUodGFyZ2V0X3ltaW49dGFyZ2V0X3Byb3AtdGFyZ2V0X0NJTG93LHRhcmdldF95bWF4PXRhcmdldF9wcm9wK3RhcmdldF9DSUhpZ2gsY29tcGV0aXRvcl95bWluPWNvbXBldGl0b3JfcHJvcC1jb21wZXRpdG9yX0NJTG93LGNvbXBldGl0b3JfeW1heD1jb21wZXRpdG9yX3Byb3ArY29tcGV0aXRvcl9DSUhpZ2gsY2VudGVyX3ltaW49Y2VudGVyX3Byb3AtY2VudGVyX0NJTG93LGNlbnRlcl95bWF4PWNlbnRlcl9wcm9wK2NlbnRlcl9DSUhpZ2gsb3RoZXJfeW1pbj1vdGhlcl9wcm9wLW90aGVyX0NJTG93LG90aGVyX3ltYXg9b3RoZXJfcHJvcCtvdGhlcl9DSUhpZ2gpCgojIHByZXBhcmUgZGF0YSBmb3IgcGxvdHRpbmcKbG9uZ19wcm9wcyA9IGFnciAlPiUgCiAgc2VsZWN0KGNvbmRpdGlvbixiaW5uZWRfdGltZV9yZWxhdGl2ZSx0YXJnZXRfcHJvcCxjb21wZXRpdG9yX3Byb3AsY2VudGVyX3Byb3Asb3RoZXJfcHJvcCkgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gdGFyZ2V0X3Byb3A6b3RoZXJfcHJvcCxuYW1lc190bz1jKCJyZWdpb24iKSx2YWx1ZXNfdG89YygicHJvcG9ydGlvbiIpKSAlPiUgCiAgc2VwYXJhdGUocmVnaW9uLGMoInJlZ2lvbiIsTkEpKQoKbG9uZ195bWluID0gYWdyICU+JSAKICBzZWxlY3QoY29uZGl0aW9uLGJpbm5lZF90aW1lX3JlbGF0aXZlLHRhcmdldF95bWluLGNvbXBldGl0b3JfeW1pbixjZW50ZXJfeW1pbixvdGhlcl95bWluKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSB0YXJnZXRfeW1pbjpvdGhlcl95bWluLG5hbWVzX3RvPWMoInJlZ2lvbiIpLHZhbHVlc190bz1jKCJ5bWluIikpICU+JSAKICBzZXBhcmF0ZShyZWdpb24sYygicmVnaW9uIixOQSkpCgpsb25nX3ltYXggPSBhZ3IgJT4lIAogIHNlbGVjdChjb25kaXRpb24sYmlubmVkX3RpbWVfcmVsYXRpdmUsdGFyZ2V0X3ltYXgsY29tcGV0aXRvcl95bWF4LGNlbnRlcl95bWF4LG90aGVyX3ltYXgpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IHRhcmdldF95bWF4Om90aGVyX3ltYXgsbmFtZXNfdG89YygicmVnaW9uIiksdmFsdWVzX3RvPWMoInltYXgiKSkgJT4lIAogIHNlcGFyYXRlKHJlZ2lvbixjKCJyZWdpb24iLE5BKSkKCnRvcGxvdCA9IGxvbmdfcHJvcHMgJT4lIAogIGxlZnRfam9pbihsb25nX3ltaW4sYnk9YygiY29uZGl0aW9uIiwiYmlubmVkX3RpbWVfcmVsYXRpdmUiLCJyZWdpb24iKSkgJT4lIAogIGxlZnRfam9pbihsb25nX3ltYXgsYnk9YygiY29uZGl0aW9uIiwiYmlubmVkX3RpbWVfcmVsYXRpdmUiLCJyZWdpb24iKSkgJT4lIAogIG11dGF0ZShyZWdpb24gPSBmY3RfcmVsZXZlbChyZWdpb24sInRhcmdldCIsImNvbXBldGl0b3IiLCJjZW50ZXIiKSkKYGBgCgpgYGB7ciBmaWcxLCAgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9Nn0KZ2dwbG90KHRvcGxvdCwgYWVzKHg9YmlubmVkX3RpbWVfcmVsYXRpdmUseT1wcm9wb3J0aW9uKSkgKwogIGdlb21fbGluZShzaXplPTEsIGFlcyhjb2xvcj1yZWdpb24pKSArCiAgZ2VvbV9yaWJib24oYWVzKHltaW49eW1pbix5bWF4PXltYXgsZmlsbD1yZWdpb24pLGFscGhhPS4zKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jYlBhbGV0dGVbMjo1XSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jYlBhbGV0dGVbMjo1XSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQ9MjAwKSxsaW5ldHlwZT0iZGFzaGVkIixzaXplPTEpICsKICAjZ2VvbV92bGluZShkYXRhPWR1cmF0aW9ucyxhZXMoeGludGVyY2VwdD1tZWFuX2F1ZGlvX29mZnNldCsyMDApLGxpbmV0eXBlPSJkYXNoZWQiLHNpemU9MSkgKwogIHhsYWIoIlRpbWUgaW4gbXMgcmVsYXRpdmUgdG8gdGFyZ2V0IHdvcmQgb25zZXQiKSArCiAgeWxhYigiUHJvcG9ydGlvbiBvZiBsb29rcyIpICsKICAjZ2VvbV90ZXh0KGRhdGE9YW5ub3RhdGlvbnMsYWVzKGxhYmVsPUxhYmVsKSkgKwogIGZhY2V0X3dyYXAofmNvbmRpdGlvbixucm93PTMpCmBgYA==